package de.stefanocke.roo.wicket.templates

import de.stefanocke.roo.wicket.Stereotypes

class EntityModelTemplate extends JavaHtmlTemplate{
	
	override String javaClassNameWhenNew(){
		"EntityModel"
	}
	
	override String stereotype(){
		Stereotypes::ENTITY_MODEL
	}
	
	override subPackageToUseWhenNew(){
		"common"
	}
	
	override buildJavaContents(){
		import_("java.io.Serializable")
		import_("org.apache.wicket.model.IModel")
		val Identifiable = import_(typeof(IdentifiableTemplate).generatedJavaType)
		'''
		/**
		 * The base class for all Entity models.
		 */
		«stereotypeAnnotation»
		@SuppressWarnings("serial")
		public abstract class «simpleTypeName»<E, ID extends Serializable> 
			implements IModel<E> {
		
			private ID id;
		
			private transient E instance;
		
			/**
			 * Workaround for ITD base code gen, since it seems not to handle generic arguments
			 * in constructors properly.
			 * 
			 * @param id
			 * @param entity
			 */
			@SuppressWarnings("unchecked")
			public EntityModel(Object id, Object entity){
				this((ID)id, (E)entity);
			}
			public EntityModel(){
			}
			
			public EntityModel(ID id, E entity) { //Should be 2 separate constructors, but then we get into type erasure trouble
				if(id!=null){
					this.id = id;
				} else if(entity!=null){
				
				this.id = getId(entity);
				instance = entity;
				} else {
					throw new IllegalArgumentException("Exactly on of id or entity must be non-null.");
				}
			}
		
			public ID getId() {
				return id;
			}
		
			@SuppressWarnings("unchecked")
			protected ID getId(E entity) {
				if (entity instanceof «Identifiable») {
					return ((«Identifiable»<ID>) entity).getId();
				} else {
					throw new UnsupportedOperationException("The entity "
							+ entity.getClass() + " does not implement «Identifiable». "
							+ "Please override getId Method in subclass.");
				}
			}
		
			public E getObject() {
				if (instance == null) {
					if (id != null) {
						instance = load(id);
					}
				}
				return instance;
			}
		
			protected abstract E load(ID id);
		
			public void setObject(E object) {
				if (object == null) {
					id = null;
				} else {
					id = getId(object);
				}
				instance = object;
			}
		
			public void detach() {
				if (instance != null && getId(instance) != null) {
					this.id = getId(instance);
				}
				if (this.id != null) {
					instance = null;
				}
			}
		}
		'''
	}
	
	
}